package com.wzw.basics.concurrent.lock.fair;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 公平锁与非公平锁
 *  1.公平锁：公平锁就是很公平，在并发环境中，每个线程在获取锁时会先查看此锁维护的等待队列，如果为空，或者当前线程是等待队列的第一个，就占有锁，否则就会加入到等待队列中，以后会按照FIFO的规则从队列中取到自己。
 *          代表：
 *              1.new ReentrantLock(true)
 *
 *  2.非公平锁：非公平锁比较粗鲁，上来就直接尝试占有锁，如果尝试失败，就再采用类似公平锁那种方式。
 *          代表：
 *              1.Synchronized
 *              2.new ReentrantLock(false)
 * @author Wangzhiwen
 */
public class FairAndNoneFairLock {

    /**
     * ReentrantLock 公平与非公平原理解析
     *  都是依靠AQS框架实现的公平与非公平
     *  公平锁抢占锁时，会调用 AQS 的 hasQueuedPredecessors 方法判断当前队列是否为空或者自己就是第一个节点。满足时才会获取锁
     */
    public static void main(String[] args) {
        Lock noneFairLock = new ReentrantLock();

        /*
         *         final void lock() {
         *             if (compareAndSetState(0, 1))
         *                 setExclusiveOwnerThread(Thread.currentThread());
         *             else
         *                 acquire(1);
         *         }
         */
        noneFairLock.lock();

        noneFairLock.unlock();

        Lock fairLock = new ReentrantLock(true);

        /*
         *         队列头结点为空，或者 头结点的后继节点不为空且节点里的线程是自己才放行
         *         public final boolean hasQueuedPredecessors() {
         *             Node t = tail;
         *             Node h = head;
         *             Node s;
         *             return h != t && ((s = h.next) == null || s.thread != Thread.currentThread());
         *         }
         *
         *         protected final boolean tryAcquire(int acquires) {
         *             final Thread current = Thread.currentThread();
         *             int c = getState();
         *             if (c == 0) {
         *                 if (!hasQueuedPredecessors() &&
         *                     compareAndSetState(0, acquires)) {
         *                     setExclusiveOwnerThread(current);
         *                     return true;
         *                 }
         *             }
         *             else if (current == getExclusiveOwnerThread()) {
         *                 int nextc = c + acquires;
         *                 if (nextc < 0)
         *                     throw new Error("Maximum lock count exceeded");
         *                 setState(nextc);
         *                 return true;
         *             }
         *             return false;
         *         }
         */
        fairLock.lock();

        fairLock.unlock();
    }

}

